<?php

/**
 * Acl model
 *
 * @author    Mon Zafra <monzee at gmail>
 * @copyright (c)2009 Mon Zafra
 * @license   http://monzee.wordpress.com/license New BSD
 * @version   $Id: Acl.php 38 2009-02-18 17:12:39Z monzee $
 */
class Admin_Acl
{
    protected $_adapter;
    static protected $_adapterPrefix = 'Admin_Acl';
    protected $_defaultAdapterClass = 'Admin_Acl_Doctrine';

    protected $_userRoles;
    protected $_roles;
    protected $_resource;
    protected $_permissions;

    public function __construct($adapter = null)
    {
        if (!empty($adapter) && is_string($adapter)) {
            $adapter = $this->factory($adapter);
        }
        $this->setAdapter($adapter);
    }

    static public function factory($adapterClass)
    {
        $class = self::$_adapterPrefix . '_' . ucfirst(strtolower($adapterClass));
        $adapter = new $class();
        return $adapter;
    }

    public function setAdapterPrefix($prefix)
    {
        $this->_adapterPrefix = rtrim($prefix, '_');
        return $this;
    }

    public function getAdapter()
    {
        if (null === $this->_adapter) {
            $this->_adapter = new $this->_defaultAdapterClass;
        }
        return $this->_adapter;
    }

    public function setAdapter($adapter)
    {
        $this->_adapter = $adapter;
        return $this;
    }

    /**
     * Param $roles must be an iteratable set of roles indexed by username.
     * Roles must be an array (or object with ArrayAccess interface) that
     * contains at least an 'id' field.
     *
     * e.g. setUserRoles(
     *   array('foo' => array(
     *     array('id' => 'author'),
     *     array('id' => 'moderator'),),
     * ));
     *
     * @param mixed $roles
     * @return Admin_Acl
     */
    public function setUserRoles($roles)
    {
        $this->_userRoles = $roles;
        return $this;
    }

    /**
     * Get stored role or proxy to the acl model adapter
     *
     * @return mixed
     */
    public function getUserRolesByUsername($username)
    {
        if (!isset($this->_userRoles[$username])) {
            $user = $this->getUserByUsername($username);
            $adapter = $this->getAdapter();
            return $adapter->getUserRoles($user);
        }
        return $this->_userRoles[$username];
    }

    /**
     * $resource must be a resource value compatible with the permissions model
     *
     * @param mixed $resource
     * @return mixed
     */
    public function setResource($resource)
    {
        $this->_resource = $resource;
        return $this;
    }

    /**
     * Get stored resource or proxy to acl model adapter
     *
     * @return mixed
     */
    public function getResource()
    {
        if (null === $this->_resource) {
            $adapter = $this->getAdapter();
            $args = func_get_args();
            return call_user_func_array(array($adapter, 'getResource'), $args);
        }

        return $this->_resource;
    }

    /**
     * Proxy to adapter
     * 
     * @param string $method
     * @param array  $args
     * @return mixed
     */
    public function __call($method, $args)
    {
        $adapter = $this->getAdapter();
        return call_user_func_array(array($adapter, $method), $args);
    }

}
